// s.d(t, { Z: () => MeshTrimData })
import Data from "../object/Data"
import ObservableArray from "../observer/observable.array"
import ObservableMap from "../observer/observable.map"
import Logger from "../utils/Logger"
import { TooManyTrimsError } from "../exception/trims.exception"
import { meshTrimsLength } from "../constant/shader.const"
const d = new Logger("MeshTrimData")
export default class MeshTrimData extends Data {
  numberOfTrims: number
  meshTrimsByFloorIndex: ObservableMap<any>
  meshTrimsById: ObservableMap<any>
  maxNameIndex: number
  constructor(e, t) {
    super()
    this.numberOfTrims = 0
    this.meshTrimsByFloorIndex = new ObservableMap()
    this.meshTrimsById = new ObservableMap()
    this.maxNameIndex = -1
    for (const e of t) {
      const t = e.index,
        s = new ObservableArray()
      this.meshTrimsByFloorIndex.set(`${t}`, s)
    }
    try {
      this.add(...Object.values(e))
    } catch (e) {}
  }
  add(...e) {
    const t = new Set()
    let s = !1
    if (this.maxNameIndex <= 0) {
      const t = this.meshTrimsById.values.map(e => e.nameIndex)
      const s = t.length ? Math.max(...t) : 0
      const r = e.map(e => e.nameIndex)
      const i = r.length ? Math.max(...r) : 0
      this.maxNameIndex = Math.max(s, i)
    }
    this.meshTrimsById.atomic(() => {
      this.meshTrimsByFloorIndex.atomic(() => {
        for (const r of e) {
          this.meshTrimsByFloorIndex.has(`${r.floorIndex}`) || this.meshTrimsByFloorIndex.set(`${r.floorIndex}`, new ObservableArray())
          const e = this.meshTrimsByFloorIndex.get(`${r.floorIndex}`)
          if (e.length < meshTrimsLength) {
            r.nameIndex === -1 && ((r.nameIndex = this.maxNameIndex + 1), (this.maxNameIndex = r.nameIndex))
            e.push(r)
            this.meshTrimsById.set(r.id, r)
            t.add(r.floorIndex)
          } else {
            d.debugWarn("Trims exceed floor limit (trimId, floorIndex):", r.id, r.floorIndex)
            s = !0
          }
        }
      })
    })
    t.forEach(e => {
      const t = this.meshTrimsByFloorIndex.get(`${e}`)
      this.sortList(t), this.reassignIndexes(t)
    })
    this.numberOfTrims = this.meshTrimsById.length
    this.commit()
    if (s) throw new TooManyTrimsError("Exceeding max trims")
  }
  delete(...e) {
    const t = new Set()
    this.meshTrimsByFloorIndex.atomic(() => {
      for (const s of e) {
        const e = this.meshTrimsByFloorIndex.get(`${s.floorIndex}`),
          r = e.indexOf(s)
        if (r >= 0) {
          ;(e.splice(r, 1)[0].enabled = !1), t.add(s.floorIndex), s.nameIndex === this.maxNameIndex && this.maxNameIndex--
        } else d.error("Could not delete mesh trim:" + s.id)
      }
    })
    t.forEach(e => {
      const t = this.meshTrimsByFloorIndex.get(`${e}`)
      this.reassignIndexes(t)
    })
    this.meshTrimsById.atomic(() => {
      e.forEach(e => {
        this.meshTrimsById.delete(e.id)
      })
    })
    e.length > 1 && (this.maxNameIndex = -1)
    this.numberOfTrims = this.meshTrimsById.length
    this.commit()
  }
  getTrimById(e) {
    return this.meshTrimsById.get(e)
  }
  getTrim(e, t) {
    return this.meshTrimsByFloorIndex.has(`${e}`) ? this.meshTrimsByFloorIndex.get(`${e}`).get(t) : null
  }
  getTrimsForFloor(e) {
    return this.meshTrimsByFloorIndex.has(`${e}`) ? this.meshTrimsByFloorIndex.get(`${e}`).values() : []
  }
  reassignIndexes(e) {
    e.forEach((e, t) => {
      e.index = t
    })
  }
  sortList(e) {
    e.sort((e, t) => e.index - t.index)
  }
}
